<?php

/**
 * 启动
 *
 * 更新时间: 2024-9-6
 * @version 0.0.1
 *
 */

if (session_status() == PHP_SESSION_NONE) {
    session_start();
}

/**
 * 定义框架常量
 */

define('START_MEMORY',  memory_get_usage()); // 开始内存
define('START_TIME',  microtime(true)); // 开始时间

defined('APP_DEBUG') || define('APP_DEBUG', false); // 调试模式
defined('DISPLAY_ERROR') || define('DISPLAY_ERROR', false); // 显示错误信息

define('BASE_PATH', '');
define('ROOT_PATH', str_replace('\\', '/', dirname(__DIR__) . '/')); // 项目根目录
defined('APP_PATH') || define('APP_PATH', ROOT_PATH . 'app/'); // 应用目录
defined('VIEW_PATH') || define('VIEW_PATH', ROOT_PATH . 'views/'); // 视图目录
defined('EXTEND_PATH') || define('EXTEND_PATH', ROOT_PATH . 'extend/'); // 扩展类目录

defined('CORE_PATH') || define('CORE_PATH', ROOT_PATH . 'core/'); // 框架目录
defined('RUNTIME_PATH') || define('RUNTIME_PATH', ROOT_PATH . 'runtime/'); // 临时文件目录
defined('LOG_PATH') || define('LOG_PATH', RUNTIME_PATH . 'logs/'); // 日志目录
defined('CACHE_PATH') || define('CACHE_PATH', RUNTIME_PATH . 'cache/'); // 缓存目录
defined('SESSION_PATH') || define('SESSION_PATH', RUNTIME_PATH . 'sessions/'); // SESSION 目录

defined('DEFAULT_APP') || define('DEFAULT_APP', 'home'); // 默认模块
defined('DEFAULT_CONTROLLER') || define('DEFAULT_CONTROLLER', 'Index'); // 默认控制器
defined('DEFAULT_METHOD') || define('DEFAULT_METHOD', 'index'); // 默认方法

defined('CUSTOM_ROUTE') || define('CUSTOM_ROUTE', false); // 自定义路由
defined('CLOSE_CACHE') || define('CLOSE_CACHE', false); // 全局缓存
defined('SESSION_START') || define('SESSION_START', true); // 开启会话
defined('SESSION_TYPE') || define('SESSION_TYPE', 'file'); // 会话存储类型  [file, memcache, redis]

defined('PAGE_SUFFIX') || define('PAGE_SUFFIX', false); // 页面后缀


/**
 * 加载框架函数
 */
require __DIR__ . '/functions.php';


/**
 * 错误处理
 */

error_reporting(E_ALL); // 默认显示全部错误
ini_set('display_errors', '0'); // 错误不显示给用户

function errorHandler($code, $message, $file, $line)
{
    if (!DISPLAY_ERROR) {
        // 在生产环境下，记录错误到日志文件
        $log = new Log();
        $log->debug($message . '\n' . $file . '\n' . $line);

        exit();
    } else {
        // 开启报错模式时，创建错误信息
        $errorDetails = [
            'code'    => $code,
            'message' => $message,
            'file'    => $file,
            'line'    => $line,
            'preview' => ''
        ];

        if (file_exists($errorDetails['file']) && is_readable($errorDetails['file'])) {
            $file = file($errorDetails['file']);
            $line = $errorDetails['line'];
            $offset = 5;
            $start = ($line - $offset >= 0) ? $line - $offset : 0;
            $end = ($line - $offset >= 0) ? $line + $offset : $offset * 2;

            for ($i = $start; $i != $end - 1; $i++) {
                if (!isset($file[$i])) {
                    continue;
                }

                /* 缩进 */
                $text = trim($file[$i], "\n\r\0\x0B");
                $text = str_replace(["    ", "  "], "\t", $text);
                $text = str_replace("\t", "<span class=\"tab\"></span>", $text);

                /* 索引中有2位数字 */
                $index = ($i < 9) ? "0" . ($i + 1) : ($i + 1);

                /* 高亮出错行 */
                if ($i == $line - 1) {
                    $errorDetails['preview'] .= '<p class="line" id="target"><span class="index">' . $index . '</span><span class="e-message">' . $text . '</span></p>' . PHP_EOL;
                } else {
                    $errorDetails['preview'] .= '<p class="line"><span class="index">' . $index . '</span>' . $text . '</p>' . PHP_EOL;
                }
            }
        }

        // 相对安全地将错误信息编码为 JSON
        define('JSON_ERROR_DETAILS', json_encode($errorDetails));

        // 引入错误页面模板
        include CORE_PATH . 'templates/error.php';
        exit;
    }
}

// 设置用户自定义的错误处理程序，然后触发错误
set_error_handler("errorHandler");

function customExceptionHandler($exception)
{
    echo "捕获到异常：",  $exception->getMessage(), "\n";
}

set_exception_handler("customExceptionHandler");

class Debug extends Exception
{
    // 调试模式打开后显示页面
    public function display()
    {
        if (APP_DEBUG) {
            include CORE_PATH . 'templates/debug.php';
        }
    }
}


/**
 * 自动加载当前目录下的文件
 */
spl_autoload_register(function ($class) {
    $file = CORE_PATH . str_replace('\\', '/', $class) . '.php';
    $realFile = realpath($file);

    if ($realFile !== false && file_exists($realFile) && is_readable($realFile)) {
        return require_once $file;
    } else {
        throw new Exception("File {$file} does not exist or is not readable.");
    }
});


/**
 * 路由
 */
function route()
{
    // 获取请求的 URI 并解析
    $originalUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
    $uri = strtok($originalUri, '?'); // 去除查询字符串
    $uri = substr($originalUri, strlen('/')); // 正常情况下去掉前缀 '/'（可扩展）
    $uri = str_replace(['..', '\\'], '', $uri); // 防止目录遍历

    // 移除可能存在的文件扩展名
    $cleanUri = explode('.', $uri, 2)[0] ?? '';

    // 分割URI成多个部分，并移除空部分
    $routeInfo = array_filter(explode('/', $cleanUri), 'strlen');

    // 获取应用、控制器和方法，使用默认值
    $app        = $routeInfo[0] ?? DEFAULT_APP;
    $controller = $routeInfo[1] ?? DEFAULT_CONTROLLER;
    $method     = $routeInfo[2] ?? DEFAULT_METHOD;

    // 检查控制器文件是否存在
    $controllerFile = APP_PATH . $app . '/controllers/' . ucfirst($controller) . '.php';

    if (!empty($controller) && !file_exists($controllerFile)) {
        $controller = DEFAULT_CONTROLLER;
        // 保持用户可能指定的方法，否则使用默认方法
        $method = isset($routeInfo[1]) ? $routeInfo[1] : DEFAULT_METHOD;
    }

    include_once $controllerFile; // 仅在经过检查后包含文件

    define('APP_NAME', $app);
    define('CONTROLLER_NAME', $controller);
    define('METHOD_NAME', $method);

    $controllerClass = "app\\{$app}\\controllers\\" . ucfirst($controller);

    // 分页处理
    $routeArray = [$app, $controller, $method];

    define('URL_SEGMENT', implode('/', $routeArray));

    $pageNumberFound = false;
    for ($i = 2; $i < count($routeArray); $i++) {
        if (preg_match('/^page_(.*)()*$/Ui', $routeArray[$i], $matches)) {
            define("PAGE_NUMBER",  intval($matches[1]));
            array_splice($routeArray, $i, 1);
            $pageNumberFound = true;
            break;
        }
    }

    if (!$pageNumberFound) {
        define('PAGE_NUMBER', 1);
    }

    // defined('PAGE_NUMBER') || define('PAGE_NUMBER', 1);

    if (class_exists($controllerClass)) {
        if (method_exists($controllerClass, $method)) {
            // 执行控制器类方法
            (new $controllerClass($method))->{$method}();
        } else {
            abort('404');
        }
    } else {
        // 适当地处理错误，例如抛出异常或显示错误消息
        throw new Exception("Controller class '{$controllerClass}' does not exist.");
    }
}

class graceException extends Exception
{
    // 调试模式打开后显示页面
    public function displayBug()
    {
        if (APP_DEBUG) {
            include __DIR__ . '/templates/error.php';
        }
    }
}


// 异常处理函数
function handleException($exception)
{
    // 根据不同类型的异常进行处理
    if ($exception instanceof graceException) {
        $exception->displayBug();
    } else {
        // 记录日志、显示错误信息等
    }
}

try {
    route();

    if (APP_DEBUG) {
        // 追踪调试
        $GLOBALS['traceSql'] = [];

        include __DIR__ . '/templates/trace.php';
    }
} catch (Debug $e) {
    $e->display();
}
